import React, {
  memo,
  useCallback,
  useState,
  useEffect,
  useMemo,
  useRef,
} from 'react';
import { connect } from 'dva';
import { StateWithHistory } from 'redux-undo';
import { uuid } from '@/utils/tool';
import { Dispatch } from 'umi';
import { useDrop } from 'react-dnd';
import { Menu, Item, useContextMenu, ItemParams } from 'react-contexify';
import ViewRender from '@/renderer/ViewRender';
import { PointDataItem } from '@/ui-components/common';

interface DropSourceProps {
  pstate: {
    pageData: {
      width: number;
      height: number;
      widthScale: number;
      heightScale: number;
    };
    pointData: { id: string; item: any; point: any }[];
    curPoint: any;
  };
  // scaleNum: number;
  canvasId: string;
  allType: string[];
  dispatch: Dispatch;
}

const MENU_ID = 'menu-id';
const DropSource = memo((props: DropSourceProps) => {
  const { pstate, canvasId, allType, dispatch } = props;
  let pointData = pstate ? pstate.pointData : [];
  let curPoint = pstate ? pstate.curPoint : {};
  const [{ isOver }, drop] = useDrop({
    accept: allType,
    drop: (
      item: { config: any; editableData: any; enableResizing: boolean },
      monitor,
    ) => {
      let id = uuid(6, 10);
      let parentDiv = document.getElementById(canvasId),
        pointRect = parentDiv!.getBoundingClientRect(),
        top = pointRect.top,
        left = pointRect.left,
        pointEnd = monitor.getSourceClientOffset(),
        x = pointEnd!.x < left ? 0 : pointEnd!.x - left,
        y = pointEnd!.y < top ? 0 : pointEnd!.y - top;
      dispatch({
        type: 'editorModel/addPointData',
        payload: {
          id,
          item,
          point: {
            i: id,
            x,
            y,
            w: item.enableResizing ? item.config.width : item.config.fontSize,
            h: item.enableResizing ? item.config.height : item.config.fontSize,
          },
        },
      });
      return item;
    },
    collect: (monitor) => ({
      isOver: monitor.isOver(),
      canDrop: monitor.canDrop(),
      item: monitor.getItem(),
    }),
  });
  const opacity = isOver ? 0.7 : 1;
  const container = useRef<HTMLDivElement>(null);
  // useEffect(() => {
  //   document.addEventListener('click', function(e) {
  //     console.log(e.target);
  //   });
  // }, [])
  const containerClick = (e: React.MouseEvent) => {
    if (e.target === container.current) {
      dispatch({
        type: 'editorModel/modPointData',
        payload: { id: null },
      });
    }
  };

  const onDragStart = useMemo(() => {
    return (newItem: any) => {
      const curPointData = pointData.filter((item) => item.id === newItem.i)[0];
      dispatch({
        type: 'editorModel/modPointData',
        payload: { ...curPointData },
      });
    };
  }, [dispatch, pointData]);

  const onDragStop = useMemo(() => {
    return (newItem: any) => {
      const curPointData = pointData.filter((item) => item.id === newItem.i)[0];
      dispatch({
        type: 'editorModel/modPointData',
        payload: { ...curPointData, point: newItem },
      });
    };
  }, [dispatch, pointData]);

  const onResizeStop = useMemo(() => {
    return (newItem: any) => {
      const curPointData = pointData.filter((item) => item.id === newItem.i)[0];
      const { item } = curPointData;
      const { config } = item;
      dispatch({
        type: 'editorModel/modPointData',
        payload: {
          ...curPointData,
          item: {
            ...item,
            config: { ...config, width: newItem.w, height: newItem.h },
          },
          point: newItem,
        },
      });
    };
  }, [dispatch, pointData]);

  const handleContextMenuDel = (id: string) => {
    dispatch({
      type: 'editorModel/delPointData',
      payload: { id },
    });
  };

  const handleMenuItemClick = ({
    event,
    props,
    data,
    triggerEvent,
  }: ItemParams) => {
    if (event.currentTarget.id === 'del') {
      handleContextMenuDel(props.id);
    }
  };

  const { show } = useContextMenu({
    id: MENU_ID,
  });

  const displayMenu = (e: any) => {
    show(e, { props: { id: e.currentTarget.id } });
  };

  const ContextMenu = useCallback(
    () => (
      <Menu id={MENU_ID}>
        <Item id="del" onClick={handleMenuItemClick}>
          删除
        </Item>
      </Menu>
    ),
    [handleMenuItemClick],
  );

  return (
    <>
      <div
        id={canvasId}
        ref={drop}
        style={{
          // transform: `scale(${scaleNum})`,
          position: 'relative',
          width: '100%',
          height: '100%',
        }}
      >
        <div
          ref={container}
          style={{
            position: 'absolute',
            left: 0,
            top: 0,
            width: '100%',
            height: '100%',
            opacity,
          }}
          onClick={containerClick}
        >
          {pointData.length > 0 ? (
            <React.Suspense fallback="loading">
              {pointData.map((value: PointDataItem) => {
                return (
                  <div key={value.id} id={value.id} onContextMenu={displayMenu}>
                    <ViewRender
                      canvasId={canvasId}
                      curPointId={curPoint?.id}
                      pointDataItem={value}
                      onDragStart={onDragStart}
                      onDragStop={onDragStop}
                      onResizeStop={onResizeStop}
                    />
                  </div>
                );
              })}
            </React.Suspense>
          ) : null}
        </div>
      </div>
      <ContextMenu />
    </>
  );
});

export default connect((state: StateWithHistory<any>) => {
  return {
    pstate: state.present.editorModel,
  };
})(DropSource);
